package com.project.core.jwt;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.common.exception.ErrCode;
import com.common.exception.SeException;

import java.util.Date;

public class JwtUtil {

    private static final String secret = "AX0XHH121wqXZM1xie2dian3shen4me5hao6le7890bu0zhi0dao";

    public static Integer getUserIdFromToken(String token) {
        Integer userId;
        try {
            DecodedJWT claims = getClaimsFromToken(token);
            userId = claims.getClaim(ClaimKey.USER_ID).as(Integer.class);
        } catch (Exception e) {
            throw new SeException(ErrCode.Token_Invalid, "token解析失败,token异常或已经过期！");
        }
        return userId;
    }

    /**
     * 生成令牌
     *
     * @param userId  用户id
     * @param expires 毫秒
     * @return token
     */
    public static String generateToken(Integer userId, long expires) {
        JWTCreator.Builder builder = JWT.create()
                .withClaim(ClaimKey.USER_ID, userId)
                .withIssuedAt(generateCurrentDate());
        // 设置过期时间
        if (expires >= 0) {
            long expMillis = getCurrentTimeMillis() + expires;
            Date exp = new Date(expMillis);
            builder.withExpiresAt(exp);
        }
        return builder.sign(Algorithm.HMAC256(secret));
    }

    private static DecodedJWT getClaimsFromToken(String token) {
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(secret)).build();
        try {
            return jwtVerifier.verify(token.replaceFirst("[B|b][E|e][A|a][R|r][E|e][R|r] ", "").trim());
        } catch (JWTVerificationException e) {
            throw new SeException(ErrCode.Token_Invalid, "token解析失败,token异常或已经过期！");
        }
    }

    private static long getCurrentTimeMillis() {
        return new Date().getTime();
    }

    private static Date generateCurrentDate() {
        return new Date(getCurrentTimeMillis());
    }

}
